(cl:defpackage #:abtab-memory-driver
  (:use #:common-lisp #:abtab)
  (:export
   #:abtab-memory-driver
   #:*store*
   ))

(in-package #:abtab-memory-driver)

(defvar *store* (make-hash-table :test #'equal))
(defvar *scheme* "memory")

(declaim (special *store*))

(defclass abtab-memory-driver (abtab-driver)
  ((read-position
    :accessor read-position
    :initform 0
    :initarg :read-position
    :documentation "The current read position.")))

(if (driver-registered-p *scheme*)
    (unregister-driver *scheme*))

(defun new-mem-driver (uri)
  (make-instance 'abtab-memory-driver :uri uri))

(unless (driver-registered-p *scheme*)
  (register-driver
   *scheme*
   :abtab-memory-driver
   #'new-mem-driver))

(defgeneric get-store-name (driver))

(defmethod get-store-name ((driver abtab-memory-driver))
  (puri:uri-host (puri:uri (resource-uri driver))))

(defgeneric mem-store (driver))

(defmethod mem-store ((driver abtab-memory-driver))
  (gethash (get-store-name driver)
	   *store*))

(defmethod initialize-destination ((driver abtab-memory-driver)
				   (col-names list))
  (setf (columns driver)
	col-names)
  (setf (gethash (get-store-name driver)
		 *store*)
	(make-array 0 :adjustable t :fill-pointer t))
  (reset-for-reading driver)
  t)

(defmacro with-store ((var-name driver)
		      &body body)
  `(let ((,var-name (mem-store ,driver)))
     (prog1
	 (progn ,@body)
       (setf (gethash (get-store-name driver)
		      *store*)
	     ,var-name))))

(defmethod write-record ((driver abtab-memory-driver)
			 (rec vector))
  (with-store (store driver)
    (vector-push-extend
     rec
     (mem-store driver))))

(defmethod reset-for-reading ((driver abtab-memory-driver))
  (setf (read-position driver) 0))

(defmethod read-next-record ((driver abtab-memory-driver))
  (with-store (store driver)
    (if (= (length store)
	   (read-position driver))
	nil
	(prog1
	    (aref store (read-position driver))
	  (incf (read-position driver))))))

;; no resources to clean up for this driver
(defmethod close-resource ((driver abtab-memory-driver))
  t)